package com.yqy.wordvideodemo.permission;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;


import com.yqy.wordvideodemo.permission.bean.AppPermission;
import com.yqy.wordvideodemo.permission.bean.AppSpecialPermission;
import com.yqy.wordvideodemo.permission.callback.IPermissionCallback;
import com.yqy.wordvideodemo.permission.callback.IPermissionsCallback;
import com.yqy.wordvideodemo.permission.callback.ISpecialPermissionCallback;
import com.yqy.wordvideodemo.permission.proxy.PermissionFragment;
import com.yqy.wordvideodemo.permission.utils.GotoUtil;
import com.yqy.wordvideodemo.permission.utils.PerCommonUtil;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import static com.yqy.wordvideodemo.permission.utils.GotoUtil.gotoHuaweiPermission;
import static com.yqy.wordvideodemo.permission.utils.GotoUtil.gotoMeizuPermission;
import static com.yqy.wordvideodemo.permission.utils.GotoUtil.gotoMiuiPermission;
import static com.yqy.wordvideodemo.permission.utils.SpecialUtil.checkSpecialPermissions;


/**
 * 申请权限帮助类
 * Created by 陈健宇 at 2019/3/25
 */
public class PermissionHelper {

    private static final String TAG_PERMISSION_FRAGMENT = PermissionFragment.class.getName();
    private Activity mActivity;
    private static PermissionHelper sinstance = null;

    private PermissionHelper() {
    }

    public static PermissionHelper getInstance() {
        if (sinstance == null) {
            synchronized (PermissionHelper.class) {
                PermissionHelper permissionHelper;
                if (sinstance == null) {
                    permissionHelper = new PermissionHelper();
                    sinstance = permissionHelper;
                }
            }
            sinstance = new PermissionHelper();
        }
        return sinstance;
    }

    /**
     * 必须传入的Activity
     */
    public PermissionHelper with(Activity activity) {
        this.mActivity = activity;
        return this;
    }

    /**
     * 可以再基类中统一传入Activity，就无需每次调用with方法
     */
    public void init(Activity activity) {
        this.mActivity = activity;
    }

    public void onCancel() {
        this.mActivity = null;
    }

    /**
     * 请求单个权限
     *
     * @param name     权限名
     * @param callback 权限申请回调
     */
    @SuppressLint("NewApi")
    public void requestPermission(@NonNull String name, IPermissionCallback callback) {
        String[] requestPermissions = checkPermissions(new String[]{name});
        if (requestPermissions.length == 0) {
            callback.onAccepted(new AppPermission(name));
            return;
        }
        getPermissionFragment(mActivity).requestPermissions(
                requestPermissions,
                (permissionsResult) -> handlePermissionResult(callback, permissionsResult[0])
        );
    }

    /**
     * 请求多个权限
     *
     * @param permissions 权限列表
     * @param callback    权限申请回调
     */
    @SuppressLint("NewApi")
    public void requestPermissions(@NonNull String[] permissions, @NonNull IPermissionsCallback callback) {
        String[] requestPermissions = checkPermissions(permissions);
        if (requestPermissions.length == 0) {
            callback.onAccepted(PerCommonUtil.toList(permissions));
            return;
        }
        getPermissionFragment(mActivity).requestPermissions(
                requestPermissions,
                (permissionsResult) -> handlePermissionsResult(callback, permissionsResult)
        );
    }

    @SuppressLint("NewApi")
    public void requestSpecialPermission(@NonNull AppSpecialPermission specialPermission, @NonNull ISpecialPermissionCallback callback) {
        if (checkSpecialPermission(specialPermission)) {
            callback.onAccepted(specialPermission);
            return;
        }
        getPermissionFragment(mActivity).requestSpecialPermission(
                specialPermission,
                (permissionsResult) -> handleSpecialPermissionResult(permissionsResult[0], callback)
        );
    }


    /**
     * 检查单个权限是否申请过
     *
     * @param name 要检查的权限名
     * @return true表示申请过，false反之
     */
    public boolean checkPermission(String name) {
        verfiy();
        return checkPermissions(new String[]{name}).length == 0;
    }

    /**
     * 检查多个权限是否申请过
     *
     * @param permissions 多个权限数组
     * @return 返回还没有被授权同意的权限数组，如果数组.length==0, 说明permissions都被授权同意了
     */
    public String[] checkPermissions(@NonNull String[] permissions) {
        verfiy();
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return new String[]{};
        List<AppPermission> rejectedPermissions = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(mActivity, permission) != PackageManager.PERMISSION_GRANTED) {
                rejectedPermissions.add(new AppPermission(permission));
            }
        }
        return PerCommonUtil.toArray(rejectedPermissions);
    }

    /**
     * 检查特殊权限是否申请过
     *
     * @param special 要检查的特殊权限
     * @return true表示申请过，false反之
     */
    public boolean checkSpecialPermission(AppSpecialPermission special) {
        verfiy();
        return checkSpecialPermissions(special, mActivity);
    }

    /**
     * 跳转到不同厂商的Permission设置界面，不满足条件，默认跳到应用详情界面
     */
    public void gotoPermissionDetail() {
        verfiy();
        gotoPermissionDetail(0x9155);
    }

    /**
     * 跳转到不同厂商的Permission设置界面，不满足条件，默认跳到应用详情界面
     * 可以带请求码跳转，需要自行重写OnActivityResult（）
     * 在OnActivityResult中根据请求码再次检查之前被用户拒绝的权限，看用户有没有打开该权限
     *
     * @param requestCode 请求码
     */
    public void gotoPermissionDetail(int requestCode) {
        verfiy();
        String brand = Build.BRAND;
        if (TextUtils.equals(brand.toLowerCase(), "redmi") || TextUtils.equals(brand.toLowerCase(), "xiaomi")) {
            gotoMiuiPermission(mActivity, requestCode);
        } else if (TextUtils.equals(brand.toLowerCase(), "meizu")) {
            gotoMeizuPermission(mActivity, requestCode);
        } else if (TextUtils.equals(brand.toLowerCase(), "huawei") || TextUtils.equals(brand.toLowerCase(), "honor")) {
            gotoHuaweiPermission(mActivity, requestCode);
        } else {
            GotoUtil.gotoAppDetail(mActivity, requestCode);
        }
    }

    /**
     * 跳转到应用详情页
     */
    public void gotoAppDetail() {
        verfiy();
        gotoAppDetail(0x9156);
    }

    /**
     * 跳转到应用详情页，带请求码
     *
     * @param requestCode 请求码
     */
    public void gotoAppDetail(int requestCode) {
        verfiy();
        GotoUtil.gotoAppDetail(mActivity, requestCode);
    }

    private void handlePermissionResult(IPermissionCallback callback, AppPermission permission) {
        if (permission.granted) {
            callback.onAccepted(permission);
        } else {
            if (permission.shouldShowRequestPermissionRationable) {
                callback.onDenied(permission);
            } else {
                callback.onDeniedAndReject(permission);
            }
        }
    }

    private void handlePermissionsResult(@NonNull IPermissionsCallback callback, AppPermission[] permissionsResult) {
        List<AppPermission> grantedPermissions = new ArrayList<>();
        List<AppPermission> deniedPermissions = new ArrayList<>();
        List<AppPermission> deniedAndRejectedAndPermissions = new ArrayList<>();
        for (int i = 0; i < permissionsResult.length; i++) {
            AppPermission permission = permissionsResult[i];
            if (permission.granted) {
                grantedPermissions.add(permission);
            } else {
                deniedPermissions.add(permission);
                if (!permission.shouldShowRequestPermissionRationable) {
                    deniedAndRejectedAndPermissions.add(permission);
                }
            }
        }
        if (grantedPermissions.size() == permissionsResult.length) {
            if (!grantedPermissions.isEmpty()) callback.onAcceptedAll();
        } else {
            if (!grantedPermissions.isEmpty()) callback.onAccepted(grantedPermissions);
            if (!deniedPermissions.isEmpty()) callback.onDenied(deniedPermissions);
            if (!deniedAndRejectedAndPermissions.isEmpty())
                callback.onDeniedAndReject(deniedPermissions, deniedAndRejectedAndPermissions);
        }
    }

    private void handleSpecialPermissionResult(AppPermission permission, ISpecialPermissionCallback callback) {
        if (permission.granted) {
            callback.onAccepted(permission.specialPermission);
        } else {
            callback.onDenied(permission.specialPermission);
        }
    }

    private PermissionFragment getPermissionFragment(Activity activity) {
        verfiy();
        if (!(activity instanceof FragmentActivity))
            throw new IllegalArgumentException("The argument passed must be FragmentActivity or it's sub class");
        FragmentManager manager = ((FragmentActivity) activity).getSupportFragmentManager();
        PermissionFragment fragment = (PermissionFragment) manager.findFragmentByTag(TAG_PERMISSION_FRAGMENT);
        if (fragment == null) {
            fragment = PermissionFragment.newInstance();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.add(fragment, TAG_PERMISSION_FRAGMENT)
                    .commitNowAllowingStateLoss();
//            try{
//                manager.executePendingTransactions();
//            }catch (IllegalStateException e){
//                e.printStackTrace();
//            }
        }
        return fragment;
    }

    private void verfiy() {
        if (mActivity == null)
            throw new NullPointerException("The Activity is null, must call with(Activity acitity) after getInstance()!");
    }

    public String getShowDialogMessage(List<AppPermission> permissions) {

        List<String> showStrings = new ArrayList<>();
        for (AppPermission per :
                permissions) {
            switch (per.name) {
                case Manifest.permission.ACCESS_FINE_LOCATION:
                case Manifest.permission.ACCESS_COARSE_LOCATION:
                    showStrings.add("定位");
                    break;
                case Manifest.permission.CAMERA:
                    showStrings.add("相机");
                    break;
                case Manifest.permission.WRITE_EXTERNAL_STORAGE:
                case Manifest.permission.READ_EXTERNAL_STORAGE:
                    showStrings.add("储存空间");
                    break;
                case Manifest.permission.READ_PHONE_STATE:
                    showStrings.add("电话");
                    break;
                case Manifest.permission.RECORD_AUDIO:
                    showStrings.add("语音录制");
                    break;
            }
        }
        showStrings = removeDuplicate(showStrings);

        StringBuilder stringBuffer = new StringBuilder();
        for (int i = 0; i < showStrings.size(); i++) {

            stringBuffer.append("\"")
                    .append(showStrings.get(i))
                    .append("\"");

            if (i < showStrings.size() - 1) {
                stringBuffer.append("、");
            }
        }

        return "请在打开的窗口的权限中开启" + stringBuffer + ",权限，以便您正常使用本应用";
    }

    /**
     * List<String>去重
     **/
    private List<String> removeDuplicate(List<String> list) {
        Set<String> set = new LinkedHashSet<String>(list);
        list.clear();
        list.addAll(set);
        return list;
    }


}
